home *** CD-ROM | disk | FTP | other *** search
/ Cream of the Crop 1 / Cream of the Crop 1.iso / UTILITY / CMDED2E6.ARJ / CMDEDIT.ASM < prev    next >
Assembly Source File  |  1992-06-30  |  53KB  |  1,928 lines

  1. ;
  2. ; CMDEDIT.ASM
  3. ; (c) 1989, 1990 PC Magazine and Ashok P. Nadkarni
  4. ; Addition of /c,l,w,n,o,t & z options by David Abbott (dfa), Nov-Dec, 1990.
  5. ; also /k option May 1991, /n July 1991 and /a June 1992.
  6. ; Additional commands and options authored by Wayne Davison (wd) have also
  7. ; been added to this version by dfa in May 1992.
  8. ; /y added by wd and dfa and /x by wd June 1992.
  9. ; Places in the code that have been changed or added by dfa have a suitable
  10. ; comment attached so a search for "dfa" will find them.  Likewise changes
  11. ; authored by wd are commented so that a search for "wd" will find them.
  12. ;
  13. ; A note on EXTRA_HANDLER (defined in COMMON.INC) by wd:
  14. ; Support for a secondary readline entry point has been added by wd.  It is
  15. ; conditionally compiled and turned off in the code.  It is ONLY intended for
  16. ; experienced programmers who know what they are doing!
  17. ; The reason for this is to support programs (such as the epsilon editor)
  18. ; that take over the readline function themselves (epsilon allows a command
  19. ; shell in a window).  In such a senario command.com is modified to use the
  20. ; int 21 function 0xEA to read a command line.  cmdedit grabs this call, and
  21. ; calls the normal int 21 function 0x0A.  If it finds itself on the receiving
  22. ; end of the call, it returns back with a flag set so that the calling
  23. ; function will do the usual function 0x0A thing and return.  If someone else
  24. ; handles the input of the text line, it passes that line on to the
  25. ; alias/history/etc processing that occurs after the edited input.  The only
  26. ; problem with this code is that my modified command.com is sometimes rejected
  27. ; as invalid, which halts the system!  Otherwise it appears to work fine.
  28.  
  29.  
  30. SIGNATURE1 equ <"CMDEDIT 2.0 (c) 1990 Ziff Communications Co.">
  31. SIGNATURE2 equ <"PC Magazine">
  32. SIGNATURE3 equ <"Ashok P. Nadkarni">
  33. SIGNATURE4 equ <"Extensions by D. Abbott & W. Davison - v6">
  34.  
  35. ; Main module for command line editor.
  36.  
  37.     INCLUDE common.inc
  38.     INCLUDE general.inc
  39.     INCLUDE ascii.inc
  40.     INCLUDE buffers.inc
  41.     INCLUDE dos.inc
  42.     INCLUDE bios.inc
  43.  
  44.     PUBLIC    dos_version_major
  45.     PUBLIC    dos_version_minor
  46.     PUBLIC    resident
  47.     PUBLIC    macro_level
  48.     PUBLIC    cur_macro
  49.     PUBLIC    cur_macro_len
  50.     PUBLIC    linebuf
  51.     PUBLIC    backbuf         ;added by wd
  52.     PUBLIC    linelimit
  53.     PUBLIC    dot
  54.     PUBLIC    lastchar
  55.     PUBLIC    LINEBUF_END
  56.     PUBLIC    edit_mode
  57.     PUBLIC    default_imode
  58.     PUBLIC    caller_cursor
  59.     PUBLIC    omode_cursor
  60.     PUBLIC    pgm_name
  61.     PUBLIC    macrosize
  62.     PUBLIC    symsize
  63.     PUBLIC    dossize
  64.     PUBLIC    dirsize
  65.     PUBLIC    mfilename
  66.     PUBLIC    mfile_seen
  67.     PUBLIC    macro_ignore_char
  68.     PUBLIC    msg_flag
  69.     PUBLIC    cmdlen
  70.     PUBLIC    silent
  71.     PUBLIC    endm_cmd
  72.     PUBLIC    defs
  73.     PUBLIC    defm
  74.     PUBLIC    tsr_install_end
  75.     PUBLIC    source
  76.     PUBLIC    abort_processing
  77.     PUBLIC    disp_line
  78.     PUBLIC    set_disp_marks
  79.     PUBLIC    insert_at_dot
  80.     PUBLIC    insert_chars
  81.     PUBLIC    remove_chars
  82.     PUBLIC    erase_to_dot
  83.     PUBLIC    init_over
  84.     PUBLIC    line_to_scr
  85.     PUBLIC    get_next_line
  86.     PUBLIC    reset_line
  87.     PUBLIC    in_appl
  88.     PUBLIC    user_command
  89.     PUBLIC    our_break_handler
  90.     PUBLIC    prev_isr1b
  91.     PUBLIC    old_int21vec
  92.     PUBLIC    cmdedit_isr
  93.     PUBLIC    makeroom
  94.     PUBLIC    locate_dosenv
  95.     PUBLIC    cmdedit
  96. ;dfa added following:
  97.     PUBLIC    cursor_type
  98.     PUBLIC    disable_macro
  99.     PUBLIC    min_length
  100.     PUBLIC    cmdedit_disable
  101.  
  102.     PUBLIC    initial_currow        ;added by wd
  103.     PUBLIC    get_curpos        ;wd made PUBLIC
  104.     PUBLIC    disp_prompt        ;moved from below by wd
  105.  
  106.  
  107.     IFE    TSR
  108.     PUBLIC    cmdedit_cmd
  109.     PUBLIC    debug_loop
  110.     PUBLIC    freadline
  111.     PUBLIC    get_file_line
  112.     PUBLIC    read_cmdfile
  113. ;    PUBLIC    disp_prompt        ;moved above by wd
  114.     PUBLIC    prompt
  115.     PUBLIC    init_screen
  116.     ENDIF
  117.  
  118.  
  119. DGROUP    GROUP    CSEG
  120.  
  121. CSEG    SEGMENT    PARA PUBLIC 'CODE'
  122.     EXTRN    install_begin:BYTE
  123.     EXTRN    install:PROC
  124.     EXTRN    execute_defs:PROC
  125.     EXTRN    execute_defm:PROC
  126.     EXTRN    execute_dels:PROC
  127.     EXTRN    execute_delm:PROC
  128.     EXTRN    execute_cmdstat:PROC
  129.     EXTRN    execute_pushd:PROC
  130.     EXTRN    execute_popd:PROC
  131.     EXTRN    execute_chd:PROC
  132.     EXTRN    hist_init:PROC
  133.     EXTRN    hist_type:PROC
  134.     EXTRN    hist_top:PROC
  135.     EXTRN    dirs_init:PROC
  136.     EXTRN    macro_init:PROC
  137.     EXTRN    symbol_init:PROC
  138.     EXTRN    expand_macro:PROC
  139.     EXTRN    expand_symbol:PROC
  140.     EXTRN    get_macro_line:PROC
  141.     EXTRN    skip_whitespace:PROC
  142.     EXTRN    skip_nonwhite:PROC
  143.     EXTRN    stre_cmp:PROC
  144.     EXTRN    get_kbd_line:PROC
  145.     EXTRN    getargs:PROC
  146.     EXTRN    file_error:BYTE
  147.     EXTRN    abort_install:PROC
  148.     EXTRN    expand_var:PROC
  149.     EXTRN    execute_rsthist:PROC
  150.     EXTRN    execute_rstmac:PROC
  151.     EXTRN    execute_rstsym:PROC
  152.     EXTRN    execute_rstdir:PROC
  153. ;following added by wd
  154.     EXTRN    execute_histstat:PROC
  155.     EXTRN    execute_dirstat:PROC
  156.     EXTRN    execute_backdir:PROC
  157.     EXTRN    output_newline:PROC
  158.     EXTRN    dosify_line:PROC
  159.  
  160. ; Define important fields in the PSP.
  161.     ASSUME    CS:DGROUP
  162.     ORG    2Ch
  163. env    dw    ?    ;Segment of environment block
  164.  
  165.     ORG    80h
  166. PROMPT_BUF_SIZE EQU 80
  167. prompt    LABEL    BYTE    ;buffer used for prompt after TSRing
  168. cmdlen    DB    ?    ;Offset 80h in the PSP contains length of command
  169. ;             line when program is invoked
  170.  
  171.     ORG    80h+PROMPT_BUF_SIZE
  172. prompt_length    dw    ?
  173. cur_macro LABEL    BYTE    ;Start of area used after TSRing to
  174. ;             store the current macro expansion.
  175.  
  176.  
  177.     ASSUME    CS:DGROUP,DS:DGROUP,ES:DGROUP,SS:DGROUP
  178.     ORG    100h
  179. entry:    jmp    install
  180.  
  181. ; The following variables are LOST after TSRing since the space is
  182. ; reused for other purposes.
  183.  
  184. mfilename    db    64 DUP (0)    ;Storage for ASCIIZ filename
  185. mfile_seen    db    0        ;Indicate if command line
  186. ;                     specified an init file
  187. mfile_handle    dw    ?        ;Handle for open file
  188.  
  189. ; Entry init_over is jumped to from the installation code after all the
  190. ; command line parsing has been done. This part of the installation
  191. ; remains resident. It is not kept with the install code because that
  192. ; code sections gets overwritten with various buffers.
  193.  
  194. init_over proc    near
  195.  
  196. ; The command parameters have been parsed. Now get ready to terminate.
  197.     mov    si,offset DGROUP:install_begin
  198.                     ;First location in installation code
  199.     mov    bx,si            ; is where the buffers start.
  200.     mov    ax,dossize        ;Size of DOS history buffer
  201.     add    si,ax            ;SI <- end of DOS buffer
  202.     xor    cx,cx            ;Indicate DOS mode
  203.     call    near ptr hist_init    ;Initialize DOS history buffer
  204.     mov    bx,si            ;Repeat for directory stack
  205.     mov    ax,dirsize
  206.     add    si,ax
  207.     call    near ptr dirs_init
  208.     mov    bx,si            ;And finally for the macros
  209.     mov    ax,macrosize
  210.     add    si,ax
  211.     call    near ptr macro_init
  212.     mov    bx,si            ;And finally for the macros
  213.     mov    ax,symsize
  214.     add    si,ax
  215.     call    near ptr symbol_init
  216.  
  217.     ; SI->end of buffer area
  218. ; Read in the command file
  219.     call    near ptr init_screen     ;Need to do this because
  220. ;                     reset_line (called by
  221. ;                     execute_defm) restores cursor shape.
  222.     call    near ptr read_cmdfile
  223.  
  224. ; Initialize var source to get the next line from the keyboard.
  225.     mov    source,offset DGROUP:get_kbd_line
  226. ; All data structures initalized. Now setup stack pointer, release
  227. ; unneeded memory back to DOS, set up interrupt handler and TSR.
  228.     push    es            ;save ES
  229.     mov    es,env            ;Don't need environment block
  230.     ASSUME    ES:NOTHING
  231.     mov    ah,49h
  232.     int    21h            ;Release the block
  233.     IF    TSR
  234.     mov    ax,3521h        ;Get old interrupt vector
  235.     int    21h
  236.     mov    old_int21vec,bx        ;Remember offset
  237.     mov    old_int21vec+2,es    ;Remember segment
  238.  
  239.     mov    dx,offset DGROUP:cmdedit_isr ;Our handler
  240.                     ;DS = CS already
  241.     mov    ax,2521h        ;Set intr vector
  242.     int    21h
  243.     ENDIF
  244.     pop    es            ;Restore ES
  245.     ASSUME    ES:DGROUP
  246.  
  247.     lea    dx,STACK_SIZE+15[si]    ;Calculate end of TSR portion
  248. ;                     DX<-num bytes to keep resident
  249.     and    dl,0f0h            ;    rounded to para
  250. ;     Note DX->BEYOND last byte of program
  251.     mov    new_sp,dx        ;Remember it
  252.  
  253.     mov    resident,1        ;Indicate we're TSR
  254.  
  255.     IFE    TSR
  256. ; Don't actually TSR
  257. debug_loop:
  258. @init_over_10:
  259.     call    near ptr output_newline
  260.     lea    dx,dummy_prompt
  261.     @DispStr dx
  262.     mov    dx,offset DGROUP:debug_buf     ;Offset
  263.     mov    debug_buf,DEBUG_BUFSIZE-2
  264.     mov    ah,0Ah            ;Function code
  265.     pushf                ;Simulate interrupt
  266.     push    cs            ;Simulate interrupt
  267.     call    near ptr cmdedit_isr    ;Simulate interrupt
  268.     jmp    short @init_over_10    ;Keep looping
  269. debug_buf    db    256 DUP (?)
  270. DEBUG_BUFSIZE    equ $-debug_buf
  271. dummy_prompt    db    "dummy>",DOLLAR
  272.     ENDIF
  273.  
  274.     int    27h            ;TSR
  275. init_over endp
  276.  
  277.  
  278. ;+
  279. ; FUNCTION : read_cmdfile
  280. ;
  281. ;    Reads commands from a file. The filename is in the variable
  282. ;    mfilename. The space occupied this function is overwritten
  283. ;    after TSRing so it must NOT be called once the program is resident.
  284. ;
  285. ; Parameters:
  286. ;    None.
  287. ;
  288. ; Returns:
  289. ;    AX =    0 on success, any other value if failure
  290. ;
  291. ; Register(s) destroyed:
  292. ;    AX,BX,CX,DX
  293. ;-
  294. read_cmdfile proc near
  295.     @save    si,di
  296.     cmp    mfile_seen,0
  297.     je    @read_cmdfile_100    ;No file specified
  298.  
  299.     @OpenFil mfilename,0
  300.     jc    @read_cmdfile_92    ;CF=1 for errors
  301. @read_cmdfile_30:
  302.     mov    source,offset DGROUP:get_file_line
  303. ;                    We want get_next_line to read
  304. ;                    from the file.
  305.     mov    mfile_handle,ax        ;Save file handle
  306.  
  307. @read_cmdfile_50:
  308.     mov    dx,offset DGROUP:linebuf ;Destination for file line
  309.     mov    ax,LINEBUF_SIZE
  310.     call    near ptr freadline    ;Get next line into buffer
  311.                     ;AX contains line length
  312.     jnc    @read_cmdfile_80    ;no error or EOF
  313.     or    ax,ax            ;No more bytes ?
  314.     jz    @read_cmdfile_99    ;EOF is not error
  315.     jmp    short @read_cmdfile_90    ;Error, abort install
  316. @read_cmdfile_80:
  317.     mov    dx,offset DGROUP:linebuf
  318.     add    dx,ax
  319.     mov    lastchar,dx        ;Update end of line
  320.     call    near ptr cmdedit_cmd    ;Execute as a command
  321.     jnc    @read_cmdfile_50    ;If not a command, better be a
  322. ;                     blank line
  323.     call    near ptr blankline
  324.     jnc    @read_cmdfile_50    ;Ignore blank lines
  325. ;     If not blank line and not CMDEDIT command, then error error handler
  326.  
  327. @read_cmdfile_90:
  328. ; Come here for error
  329.     @ClosFil mfile_handle        ;Close the file
  330. @read_cmdfile_92:
  331.     @DispStr file_error
  332.     mov    ax,-1            ;Indicate exit code
  333.     jmp    abort_install        ;Exit program
  334.  
  335. @read_cmdfile_99:
  336.     @ClosFil mfile_handle        ;Close the file
  337.     jc    @read_cmdfile_92    ;Abort if error closnig file
  338. @read_cmdfile_100:
  339.     @restore
  340.     ret
  341. read_cmdfile endp
  342.  
  343.  
  344.  
  345. ;+
  346. ; FUNCTION : get_file_line
  347. ;
  348. ;    Called indirectly through the global variable 'source'.
  349. ;    Currently this routine exists only during installation and must
  350. ;    NOT be called once the program is a TSR. The next line from the
  351. ;    file is copied to linebuf. If there is no next line, the
  352. ;    installation is aborted.
  353. ;
  354. ; Parameters:
  355. ;    None.
  356. ;
  357. ; Returns:
  358. ;    Nothing.
  359. ; Register(s) destroyed:
  360. ;    AX,BX,CX,DX
  361. ;-
  362. get_file_line proc near
  363.     mov    dx,offset DGROUP:linebuf
  364.     mov    ax,LINEBUF_SIZE
  365.     call    near ptr freadline
  366.     jnc    @get_file_line_99
  367. ;Error reading file or EOF
  368.     @DispStr file_error
  369.     jmp    abort_install
  370. @get_file_line_99:
  371.     mov    dx,offset DGROUP:linebuf
  372.     add    dx,ax
  373.     mov    lastchar,dx        ;Update end of line
  374.     ret
  375. get_file_line    endp
  376.  
  377.  
  378.  
  379.  
  380. ;+
  381. ; FUNCTION : freadline
  382. ;
  383. ;    Reads a line at a time from the file whose handle is in
  384. ;    mfile_handle into the buffer pointed to by AX. If the buffer is
  385. ;    too small or if there are any errors, the routine returns with CF set.
  386. ;    If EOF, then AX = 0 and CF is set.
  387. ;
  388. ; Parameters:
  389. ;    DX    = address of buffer
  390. ;     AX    = size of buffer
  391. ;
  392. ; Returns:
  393. ;    CF     = 0 if no errors (and not EOF), else 1.
  394. ;    AX    = num chars in line if CF = 0.
  395. ;          0 if EOF, ffff for other errors if CF = 1
  396. ;
  397. ; Register(s) destroyed:
  398. ;-
  399. freadline proc    near
  400.     @save    si,di
  401.     mov    di,dx            ;DI->buffer
  402.     mov    bx,mfile_handle
  403.     mov    si,ax            ;SI<-num bytes to read
  404.     xchg    cx,ax            ;CX<-num bytes to read
  405.     mov    ah,3Fh            ;File read function
  406.     int    21h
  407.     jc    @freadline_99        ;Error!
  408.     mov    cx,ax            ;CX<-num bytes read
  409.     jcxz    @freadline_99_a        ;EOF (note AX is 0 indicating EOF)
  410.     xchg    dx,ax            ;DX<-num bytes read
  411.     mov    bx,di            ;BX->start of buffer
  412.     mov    al,CR
  413.     repne    scasb            ;Hunt for CR
  414.     je    @freadline_50        ;Found
  415. ;    No CR found, this better be the last line in file.
  416.     cmp    dx,si            ;Were fewer bytes read than requested?
  417.     cmc
  418.     jc    @freadline_99        ;Error
  419.     push    dx            ;Save length of line
  420.     xor    ax,ax            ;AX<-num extra bytes read
  421.     jmp    short @freadline_60
  422. @freadline_50:
  423.     stc                ;Assume line too long
  424.     jcxz    @freadline_99        ;error if match in last char
  425. ;                     (line too long)
  426.     cmp    BYTE PTR [di],LF    ;Next char must be linefeed
  427.     stc                ;Assume error
  428.     jne    @freadline_99        ;Indeed an error if not LF
  429.     mov    ax,di
  430.     sub    ax,bx            ;AX<-num chars including CR
  431.     sub    dx,ax
  432.     xchg    ax,dx
  433.     dec    dx            ;DX<-num chars in line
  434.     dec    ax            ;AX<-num extra chars read
  435.     push    dx            ;Save num chars in line
  436.  
  437. @freadline_60:
  438. ; Top of stack contains num bytes in line.
  439. ; Now position file pointer to 'unread' characters.
  440. ; AX contains the num of extra characters read.
  441.     neg    ax
  442.     cwd
  443.     mov    cx,ax
  444.     xchg    cx,dx            ;CX:DX<-num bytes to 'unread'
  445.     mov    bx,mfile_handle
  446.     mov    ax,4201h        ;Move file ptr relative
  447.     int    21h            ;Seek file relative
  448. ; CF set/reset by error status
  449.     pop    ax            ;AX<-num bytes in line
  450.     clc                ;No errors
  451.     jmp    short @freadline_100
  452. @freadline_99:
  453.     mov    ax,0ffffh        ;Non-EOF error
  454. @freadline_99_a:
  455.     stc                ;Indicate error or EOF
  456. @freadline_100:
  457.     @restore
  458.     ret
  459. freadline endp
  460.  
  461.  
  462.  
  463. ;+
  464. ; FUNCTION : blankline
  465. ;
  466. ;    Checks whether the line in linebuf is blank or not. Also treats it
  467. ;    as blank line if it begins with a `-'.
  468. ;
  469. ; Parameters:
  470. ;    None.
  471. ;
  472. ; Returns:
  473. ;    CF    = 0 if blank line, else 1.
  474. ; Register(s) destroyed:
  475. ;    AX,BX,CX,DX
  476. ;-
  477. blankline proc    near
  478.     @save    si
  479.     mov    si,offset DGROUP:linebuf
  480.     cmp    byte ptr [si],'-'        ;Comment char ?
  481.     jne    @blankline_20
  482.     clc
  483.     jmp    short @blankline_99
  484. @blankline_20:
  485.     mov    cx,lastchar
  486.     sub    cx,si            ;CX<-num chars in line
  487.     call    near ptr skip_whitespace ;CF=1 if end of string
  488.     cmc
  489. @blankline_99:
  490.     @restore
  491.     ret
  492. blankline endp
  493.  
  494.  
  495. ; Extend the resident part of the installation code to form a buffer to
  496. ; hold the prompt and one to hold the current macro line arguments.
  497. ;  - 128 bytes from PSP + initial portion of CSEG.
  498. tsr_install_end LABEL BYTE
  499.     IF    ($-entry) LT (2+PROMPT_BUF_SIZE+LINEBUF_SIZE - 128)
  500.     DB    (2+PROMPT_BUF_SIZE+LINEBUF_SIZE - 128 - ($-entry)) DUP (?)
  501.     ENDIF
  502.  
  503. pgm_name db    SIGNATURE1,CR,LF
  504. copyrite db    SIGNATURE2,32,254,32,SIGNATURE3,CR,LF,SIGNATURE4,CR,LF,CR,LF,DOLLAR,26
  505.  
  506. ; Major and minor DOS versions.
  507. dos_version_major    db    ?
  508. dos_version_minor    db    ?
  509.  
  510. ;dos_envseg    dw    0         ;Segment for DOS
  511. ;                     environment. 0 indicates
  512. ;                     we don't know it.
  513.  
  514. resident    db    0        ;1 after becoming resident
  515. abort_entry_stack dw ?            ;Storage for stack state to be
  516. ;                     restored when processing is aborted
  517. abort_msg_hd db '*** CMDEDIT : '    ;Header for abort message
  518. ABORT_HDR_LEN   equ $-abort_msg_hd
  519. abort_msg_hd2 db LF            ;dfa's header for abort message
  520. ABORT_HDR2_LEN   equ $-abort_msg_hd2
  521. abort_msg_tl db ' Any ongoing macro aborted! ***' ;Tail for abort message
  522. ABORT_TAIL_LEN  equ $-abort_msg_tl
  523. abort_msg_tl2 db '   '            ;dfa's tail for abort message
  524. ABORT_TAIL2_LEN  equ $-abort_msg_tl2
  525.  
  526. ; The following are error messages displayed by routine abort_processing.
  527. ; ALL MESSAGES MUST BE SHORT ENOUGH TO FIT INTO LINEBUF TOGETHER WITH
  528. ; abort_msg_hd and abort_msg_tl. The order of messages must be same as
  529. ; the order of Error code definitions in file common.inc
  530. abort_msg_table LABEL    BYTE
  531. line_trunc_msg     db    'Line too long.'
  532. saw_sig_msg     db    'Command aborted by user.'
  533. dirstk_empty_msg db    'Directory stack empty.'
  534. dirstk_msg     db    'Invalid dir or stack full.'
  535. dirstk_only_dos     db    'Command is DOS only.'
  536. nested_macro_msg db    'Nested macro definition.'
  537. nested_delm_msg     db    'DELM used inside macro.'
  538. ctrl_brk_msg     db    'Control-Break.'
  539. abort_msg_end    LABEL    BYTE
  540.  
  541. ; The following table holds pointers to each entry in the message table
  542. ; above. The length of each message is also stored here.
  543. abort_msg_ptrs    LABEL    WORD
  544.         dw    line_trunc_msg
  545.         dw    saw_sig_msg-line_trunc_msg
  546.         dw    saw_sig_msg
  547.         dw    dirstk_empty_msg-saw_sig_msg
  548.         dw    dirstk_empty_msg
  549.         dw    dirstk_msg-dirstk_empty_msg
  550.         dw    dirstk_msg
  551.         dw    dirstk_only_dos-dirstk_msg
  552.         dw    dirstk_only_dos
  553.         dw    nested_macro_msg-dirstk_only_dos
  554.         dw    nested_macro_msg
  555.         dw    nested_delm_msg-nested_macro_msg
  556.         dw    nested_delm_msg
  557.         dw    ctrl_brk_msg-nested_delm_msg
  558.         dw    ctrl_brk_msg
  559.         dw    abort_msg_end-ctrl_brk_msg
  560.  
  561. macrosize    dw    512    ;Default size of macro buffer
  562. symsize        dw    512    ;Default size of symbol buffer
  563. dossize        dw    512    ;Default size of DOS history buffer
  564. dirsize        dw    128    ;Default size of directory stack buffer
  565.  
  566. ;+-------------------------+
  567. ;| CMDEDIT state variables |
  568. ;+-------------------------+
  569. ; The variables source and macro_level together indicate the source of
  570. ; the next line. If macro_level is non-zero, the next line is obtained
  571. ; from an ongoing macro expansion. If macro_level is 0, then the
  572. ; variable source contains the address of the function to call to
  573. ; return the next line. This will be either get_kbd_line, get_int21_line (wd),
  574. ; or get_file_line.
  575. macro_level    dw    0
  576. source        dw    ?        ;filled in during initialization
  577.  
  578.  
  579. ;+----------------------------------------------------------+
  580. ;| CMDEDIT commands. All commands preceded by a length byte.|
  581. ;| For each command that is added, make sure you update the |
  582. ;| table cmd_func_table below.                    |
  583. ;+----------------------------------------------------------+
  584. cmd_table    LABEL    BYTE
  585. defs        db    4,'defs'    ;Define a single line macro
  586. defm        db    4,'defm'    ;Start multiline macro definition
  587. pushd        db    5,'pushd'    ;Push on directory stack
  588. popd        db    4,'popd'    ;Pop from directory stack
  589. chd        db    3,'chd'        ;Change disk and directory
  590. dels        db    4,'dels'    ;Delete a symbol
  591. delm        db    4,'delm'    ;Delete a macro
  592. rsthist        db    7,'rsthist'    ;Reset history stack
  593. rstmac        db    6,'rstmac'    ;Reset macro buffer
  594. rstsym        db    6,'rstsym'    ;Reset symbol buffer
  595. rstdir        db    6,'rstdir'    ;Reset directory stack
  596. cmdstat        db    7,'cmdstat'    ;Show macro and symbol status
  597. ;following added by wd:
  598. histstat    db    7,'history'    ;Show history
  599. dirstat     db    4,'dirs'    ;Show directory stack
  600. backdir     db    4,'back'    ;Change to previous directory
  601.  
  602. cmd_table_end    db    0        ;Terminate with a 0
  603. MAX_CMD_LEN    equ    7        ;Length of longest command
  604. ; Note endm is not a command except during a macro definition.
  605. endm_cmd    db    4,'endm'    ;End multiline macro definition
  606.  
  607.  
  608. ;+--------------------------------------------------------------+
  609. ;| CMDEDIT command functions. Must be in same order as commands.|
  610. ;+--------------------------------------------------------------+
  611. cmd_func_table    label WORD
  612.         dw    execute_defs
  613.         dw    execute_defm
  614.         dw    execute_pushd
  615.         dw    execute_popd
  616.         dw    execute_chd
  617.         dw    execute_dels
  618.         dw    execute_delm
  619.         dw    execute_rsthist
  620.         dw    execute_rstmac
  621.         dw    execute_rstsym
  622.         dw    execute_rstdir
  623.         dw    execute_cmdstat
  624. ;following added by wd
  625.         dw    execute_histstat
  626.         dw    execute_dirstat
  627.         dw    execute_backdir
  628.  
  629. linebuf_kludge    db    ?        ;added by wd
  630. linebuf_prefix    db    0        ;Fill byte/Sentinel before linebuf.
  631. ;                     Used in code to allow uniform
  632. ;                     checking of first linebuf character.
  633. linebuf        db    LINEBUF_SIZE DUP (?)    ;Temporary line buffer.
  634. LINEBUF_END    equ    $
  635. linebuf_suffix    db    ?            ;Need a byte at end of
  636. ;                         linebuf in various places
  637. backbuf     db  68 DUP (0)    ;Buffer for backdir command added by wd
  638. macro_ignore_char db    ';'        ;Character used to prevent macro
  639. ;                     and symbol expansion.
  640. disable_macro    db  0    ;added by dfa. 1 to disable macro & symbol t'lation
  641. cmdedit_disable db  0    ;added by dfa. 1 to disable CMDEDIT
  642. min_length    dw  1    ;added by dfa. Minimum line length to store.
  643. msg_flag    db  0    ;added by dfa. If 1, changes error message strings
  644. lastchar    dw    ?        ;Points beyond last char in the line
  645. cur_macro_len    dw    ?        ;Length of data in cur_macro
  646. dot        dw    ?        ;Current position in line
  647. disp_begin    dw    ?        ;disp_begin and disp_end are
  648. disp_end    dw    ?        ; markers into the line buffer
  649. ;                      that are used to keep track
  650. ;                      of the range that has been
  651. ;                      changed. This is used to
  652. ;                      selectively update the display.
  653. edit_mode    db    ?        ;1 if insert mode, else 0
  654. default_imode    db    0        ;By default overtype mode
  655. cursor_type    db    0    ;Added by dfa.    Default 0 indicates unchanged
  656. ;                 for overtype mode, changed for insert mode.
  657. ;                 Set to 1 to reverse behaviour.
  658. linelimit    dw    ?        ;Upper limit for linebuf based
  659. ;                     on user's buffer length
  660. noted_dos_seg    db    0        ;1 after we have noted DOS segment
  661. dos_seg        dw    ?        ;Stores DOS segment
  662. in_appl        db    0        ;0 if dos, 1 if application
  663. user_command    db    0        ;This is set to 1 by certain
  664. ;                     CMDEDIT commands to return a
  665. ;                     string to the caller.
  666. ;                     (Basically put in as a kluge
  667. ;                     to get the prompt right after
  668. ;                     a pushd/popd/chd)
  669. ;+------------+
  670. ;| Video data |
  671. ;+------------+
  672. video_page    db    ?        ;Current video page
  673. screen_width    db    ?        ;width of screen
  674.  
  675. ;this bit changed by wd:
  676. ;initial_curcol label    byte        ;initial cursor column
  677. ;initial_curpos dw    ?        ;Initial cursor position
  678. initial_curpos    label    word        ;Initial cursor position
  679. initial_curcol    db    ?        ;initial cursor column
  680. initial_currow    db    ?        ;initial cursor row
  681.  
  682. ;Next two words must be contiguos
  683. omode_cursor    dw    ?        ;Cursor for overtype mode
  684. imode_cursor    dw    ?        ;Cursor for insert mode
  685. caller_cursor    dw    ?        ;Cursor shape of caller
  686.  
  687. silent        db    0        ;non-0 if bell should not be rung
  688.  
  689. ;+-------------------------------------------------------------------------+
  690. ;|Storage areas for various registers when called through INT 21 interface.|
  691. ;+-------------------------------------------------------------------------+
  692.  
  693. IF  EXTRA_HANDLER        ;these 3 lines added by wd
  694. ahreg    db    0Ah
  695. ENDIF
  696.  
  697. ssreg    dw    ?
  698. spreg    dw    ?
  699.  
  700. old_int21h LABEL DWORD        ;Storage for previous int 21h vector
  701. old_int21vec    DW    2 DUP (?)
  702.  
  703. new_sp    dw    ?        ;Store our stack ptr (bottom of stack).
  704.                 ;This is first para BEYOND cmdedit's memory.
  705.  
  706. prev_isr1b    dd    ?        ;Previous control break handler
  707.  
  708. ; check_break is set to 1 on entry to cmdedit, and restored to 0 on exit. If
  709. ; 1 on entry, then calling program must have been aborted with a break or
  710. ; critical error. The CMDEDIT Ctrl-Break ISR increments this flag every
  711. ; time it is called. If it is > 1, inside CMDEDIT, it indicates that a
  712. ; ctrl-break was entered. This allows runaway macros and symbols to be
  713. ; aborted.
  714. check_break    dw    0
  715. trap_break    db    0        ;If 1, does not allow original
  716. ;                     Ctrl-Break handler to see the
  717. ;                     Ctrl_break 
  718.  
  719.  
  720.  
  721. ;+
  722. ; FUNCTION : cmdedit_isr
  723. ;
  724. ;    This is our replacement for the DOS INT 21h handler.
  725. ;
  726. ; Parameters:
  727. ;    AH = function code
  728. ;
  729. ; Register(s) destroyed:
  730. ;-
  731. cmdedit_isr proc far
  732.     ASSUME    CS:DGROUP,DS:NOTHING,ES:NOTHING,SS:NOTHING
  733.     pushf                ;Save flags
  734.     cmp    ah,0Ah            ;Is it the buffered input function ?
  735.     IF  EXTRA_HANDLER        ;This bit added by wd,
  736.     je    @cmdedit_isr_4        ;slightly modified by dfa.
  737.     cmp    ah,0EAh            ;Is this the kludged input function?
  738.     ENDIF
  739.     jne    @cmdedit_isr_5        ;No. Added by dfa
  740. @cmdedit_isr_4:
  741.     cmp    cmdedit_disable,1        ;Is cmdedit disabled? ;added by dfa
  742.     jne    @cmdedit_isr_10        ;If not go on carry out our duty
  743. @cmdedit_isr_5:
  744.     popf                ;restore flags
  745.     jmp    cs:old_int21h        ;and execute the original ISR
  746. @cmdedit_isr_10:
  747.     IF  EXTRA_HANDLER        ;added by wd
  748.     xchg    cs:ahreg,ah        ;Save call type
  749.     test    ah,ah            ;and check if this is a check
  750.     js    @cmdedit_isr_20     ;If so, just return with ahreg changed
  751.     ENDIF
  752.                     ;Save registers
  753.     mov    cs:ssreg,ss        ;Stack segment
  754.     mov    cs:spreg,sp        ; and pointer
  755.     cli                ;Wanna change stack
  756.     push    cs
  757.     pop    ss
  758.     mov    sp,cs:new_sp        ;Bottom of stack
  759.     ASSUME    SS:DGROUP
  760.     sti                ;OK to interrupt now
  761.     @save    ax,bx,cx,dx,si,di,bp,ds,es
  762.     xchg    bx,dx
  763.     mov    al,byte ptr ds:[bx]    ;Length of caller buffer
  764.     xchg    dx,bx
  765.     xor    ah,ah            ;AX<-length of caller's buffer
  766.     push    ds            ;Save user segment
  767.     mov    cx,cs
  768.     mov    ds,cx            ;Init DS, ES to point to DGROUP
  769.     mov    es,cx
  770.     ASSUME    DS:DGROUP,ES:DGROUP
  771.     add    ax,offset dgroup:linebuf ;AX->last allowable linebuf
  772. ;                      location + 1
  773.     dec    ax            ;Need room for CR at end of line
  774.     mov    linelimit,ax        ;Store it
  775.     pop    ax            ;AX <- User's buffer segment
  776.                     ;DX already contains offset of
  777.                     ; user buffer
  778.     call    near ptr cmdedit    ;Main routine
  779.     @restore
  780.     cli
  781.     mov    ss,cs:ssreg
  782.     mov    sp,cs:spreg
  783.     sti
  784.     IF  EXTRA_HANDLER   ;added by wd
  785.     mov    cs:ahreg,0Ah
  786.     ENDIF
  787.  
  788. @cmdedit_isr_20:
  789.     popf
  790.     iret
  791. cmdedit_isr    endp
  792.  
  793.  
  794.  
  795.  
  796. ;+
  797. ; FUNCTION : cmdedit
  798. ;
  799. ;    Main routine called by the INT 21h ISR to get next line.
  800. ;    General Algorithm:
  801. ;    (1) Get the next line from the keyboard/macro expansion/file.
  802. ;    (2) Check for line begins with a macro. If so, expand it and
  803. ;        repeat step (2). Else go onto step (3).
  804. ;    (3) Check if the line is an internal CMDEDIT command. If so, execute
  805. ;        it and return to step (1).
  806. ;    (4) Copy line to caller's buffer and return.
  807. ;
  808. ; Parameters:
  809. ;    AX    = segment of user's buffer
  810. ;    DX    = offset of user's buffer
  811. ;
  812. ; Returns:
  813. ;    The next input line is copied into the user's buffer.
  814. ; Register(s) destroyed:
  815. ;    All except segment registers.
  816. ;-
  817. cmdedit    proc    near
  818.     push    es            ;Save ES
  819.     push    ax            ;Caller's buffer segment
  820.     push    dx            ;Caller's buffer offset
  821.     mov    trap_break,1        ;Trap Ctrl-Break handler
  822.     mov    cx,1
  823.     xchg    cx,CS:check_break    ;Check if last call did not
  824. ;                     exit normally. Also set flag
  825. ;                     for this call.
  826.     jcxz    @cmdedit_0        ;Last exit was OK
  827.     mov    macro_level,0        ;No it was not, so reset input
  828.     mov    source,offset DGROUP:get_kbd_line
  829. @cmdedit_0:
  830.     IF  EXTRA_HANDLER        ;added by wd
  831.     cmp    ahreg,0Ah        ;Is this a normal readline?
  832.     je    @cmdedit_00        ;If not, use int21 for normal readline
  833.     mov    source,offset DGROUP:get_int21_line
  834. @cmdedit_00:
  835.     ENDIF
  836.     call    near ptr init_screen    ;Get screen/cursor data
  837.  
  838.     cmp    noted_dos_seg,0        ;Have we noted the DOS segment ?
  839.     jne    @cmdedit_1        ;Jump if we know it already
  840.     mov    noted_dos_seg,1        ;Remember that we now know it
  841.     mov    dos_seg,ax        ;Else remember it
  842.                     ;No point jumping over next
  843.                     ;couple of statements.
  844. @cmdedit_1:
  845.     mov    cx,1            ;Assume caller is not DOS
  846.     cmp    ax,dos_seg        ;Is the caller DOS ?
  847.     jne    @cmdedit_2
  848.     dec    cx            ;Yes, CX<-0
  849. @cmdedit_2:
  850.     mov    in_appl,cl        ;Rememeber whether caller is dos
  851.     call    near ptr hist_type    ;Set the history type (DOS/appl)
  852.  
  853. ; cmdedit_abort_entry is the entry point when command proessing is
  854. ; aborted for any reason. It is jumped to from abort_processing
  855.     mov    abort_entry_stack,sp    ;Remember stack state
  856. cmdedit_abort_entry    LABEL PROC
  857. @cmdedit_3:
  858.     call    near ptr reset_line    ;Reset cursor, line etc.
  859.     call    near ptr get_next_line    ;Get the next line from appropriate
  860. ;                     source (stored in linebuf)
  861. @cmdedit_10:
  862.     cmp    check_break,2        ;Check for any control breaks
  863.     jb    @cmdedit_11a        ;No ctrl-breaks
  864.     mov    check_break,1
  865.     mov    ax,E_CTRL_BREAK        ;Message number
  866.     jmp    abort_processing
  867.  
  868. @cmdedit_11a:  ;added by dfa
  869. ;If macros disabled, do not do a macro or symbol expansion,  or even check
  870. ;for ignore character.
  871.     cmp disable_macro,1
  872.     jne @cmdedit_11
  873.     stc
  874.     jmp @cmdedit_25         ;Yes, exit with carry flag set
  875.  
  876. @cmdedit_11:
  877. ;If the first character is a ignore character, do not do a macro or symbol
  878. ;expansion.
  879.     mov    cx,lastchar        ;End of line
  880.     mov    si,offset DGROUP:linebuf ;SI->line buffer
  881.     sub    cx,si            ;CX<-length of line
  882.     jcxz    @cmdedit_15        ;Empty line, keep going since it
  883. ;                     can still be a macro or symbol
  884.     mov    al,[si]            ;AL<-first char of line
  885.     cmp    al,macro_ignore_char
  886.     je    @cmdedit_13
  887.     cmp    al,'@'            ;should we convert / to \ and - to / ?
  888.     jne    @cmdedit_15        ;No
  889.     call    near ptr dosify_line    ;dosify-it
  890. ; First is an ignore character so move up all characters and return
  891. @cmdedit_13:
  892.     mov    di,si            ;DI->start of line
  893.     inc    si            ;SI->first char to copy
  894.     dec    cx            ;1 less character
  895.     dec    lastchar
  896. ;    Assume ES==DS, direction flag clear
  897.     rep    movsb            ;Move the bytes
  898.     jmp    @cmdedit_25        ;Yes, exit with carry flag set
  899.  
  900. @cmdedit_15:
  901.     call    near ptr expand_symbol    ;Check if symbol and expand
  902.     jnc    @cmdedit_10        ;If expanded, recurse
  903.     call    near ptr expand_macro    ;Check if line is a macro
  904. ;                     and expand if possible.
  905.     jnc    @cmdedit_10        ;If expanded, do recursively.
  906. ;                     (note that currently recursion
  907. ;                     will take place only on the
  908. ;                     last line of a macro definition)
  909. @cmdedit_25:
  910.  
  911.     mov    user_command,0        ;Init flag
  912.     call    near ptr cmdedit_cmd    ;Check if CMDEDIT command
  913.     jc    @cmdedit_30        ;No
  914. ; CMDEDIT command, but might want to return to caller anyway.
  915.     cmp    user_command,1        ;If 1, then return string to caller
  916.     je    @cmdedit_30        ; klugery here for PUSHD/POPD/CHD
  917. ;                     to intentionally return a
  918. ;                     blank line to DOS in order to
  919. ;                     get prompt right.
  920.  
  921.     jmp    short @cmdedit_3
  922.  
  923. @cmdedit_30:
  924. ; Expand variables if any.
  925.     call    near ptr replace_vars
  926.  
  927. ; Check if line too long for user buffer.
  928.     mov    ax,lastchar        ;AX->last character in buffer
  929.     cmp    ax,linelimit
  930.     jbe    @cmdedit_80        ;We're OK
  931.     mov    ax,E_TRUNCATE        ;error - line too long
  932.     jmp    near ptr abort_processing
  933. @cmdedit_80:
  934.     sub    ax,offset DGROUP:linebuf ;AX<-length of line
  935. ; OK now we have a line to give to the caller. Copy it into caller's
  936. ; buffer and return.
  937.     pop    di            ;Caller's buffer offset
  938.     pop    es            ;Caller's buffer segment
  939.     inc    di            ;ES:DI->second byte of user buffer
  940.     stosb                ;Store line length
  941.     mov    si,offset DGROUP:linebuf ;SI->Source string
  942.     xchg    cx,ax            ;CX<-length of string
  943.     rep    movsb            ;Copy bytes
  944.     mov    al,CR
  945.     stosb                ;Store terminating carraige-return
  946. ; Set cursor shape to caller's shape
  947.     call    near ptr restore_cursor    ;Restore user's cursor shape
  948.     mov    check_break,0        ;Reset flag
  949.     mov    trap_break,0        ; Ctrl-Break handler
  950.     pop    es            ;Restore ES
  951.     ret
  952. cmdedit endp
  953.  
  954.  
  955.  
  956.  
  957.  
  958. ;+
  959. ; FUNCTION : get_next_line
  960. ;
  961. ;    Gets the next line from the appropriate source and stores it in
  962. ;    the line buffer. THe source of the line may be either a macro
  963. ;    expansion or a file or the keyboard.
  964. ;
  965. ; Parameters:
  966. ;    None.
  967. ;
  968. ; Returns:
  969. ;    Nothing
  970. ; Register(s) destroyed:
  971. ;-
  972. get_next_line proc near
  973.     mov    lastchar,offset DGROUP:linebuf
  974.                     ;Empty line (in case not
  975. ;                     already done)
  976.     call    near ptr get_macro_line    ;Get next line in expansion
  977.     jnc    @get_next_line_99    ;Jump if there is a next line
  978.                     ;No next line in expansion, so
  979.                     ;get line from keyboard/file
  980. @get_next_line_10:
  981.     call    [source]        ;get_{kbd,int21,file}_line
  982. @get_next_line_99:
  983.     ret
  984. get_next_line endp
  985.  
  986.  
  987.     IF  EXTRA_HANDLER
  988. ;+
  989. ; FUNCTION : get_int21_line by wd
  990. ;
  991. ;    Call readline through the int21 handler.  If we found ourselves,
  992. ;    the entry code changed ahreg to 0Ah and promptly returned, so use
  993. ;    this as a flag to switch to get_kbd_line if found.  Otherwise,
  994. ;    someone else handled the command input, so grab their line and
  995. ;    run with it.
  996. ;
  997. ; Parameters:
  998. ;    None.
  999. ;
  1000. ; Returns:
  1001. ;    Nothing
  1002. ; Register(s) destroyed:
  1003. ;-
  1004. get_int21_line proc near
  1005.     mov    dx,offset DGROUP:linebuf_kludge
  1006.     mov    ax,linelimit
  1007.     sub    ax,dx
  1008.     dec    ax
  1009.     mov    bx,dx
  1010.     mov    [bx],al
  1011.     mov    ah,0Ah
  1012.     int    21h
  1013.     cmp    ahreg,0Ah
  1014.     jne    get_int21_line_10
  1015.     jmp    get_kbd_line
  1016. get_int21_line_10:
  1017.     xor    ax,ax
  1018.     xchg    linebuf_prefix,al
  1019.     add    ax,offset DGROUP:linebuf
  1020.     mov    lastchar,ax
  1021.     ret
  1022. get_int21_line endp
  1023.     ENDIF
  1024.  
  1025.  
  1026.  
  1027. ;+
  1028. ; FUNCTION : replace_vars
  1029. ;
  1030. ;    Replaces all the variables in the current line with their
  1031. ;    expansions. If the line is too long, aborts with a truncation
  1032. ;    error.
  1033. ;
  1034. ; Parameters:
  1035. ;    None.
  1036. ;
  1037. ; Returns:
  1038. ;    Nothing.
  1039. ; Register(s) destroyed:
  1040. ;    AX,BX,CX,DX
  1041. ;-
  1042. replace_vars proc near
  1043.     call    near ptr expand_var        ;CF set if error. AX
  1044. ;                         contains error code
  1045.     jnc    @replace_vars_99
  1046.     jmp    near ptr abort_processing    ;Abort processing
  1047.  
  1048. @replace_vars_99:
  1049.     ret
  1050. replace_vars endp
  1051.  
  1052.  
  1053.  
  1054. ;+
  1055. ; FUNCTION : get_curpos
  1056. ;
  1057. ;    Returns the current cursor position.
  1058. ;
  1059. ; Parameters:
  1060. ;    Global    video_page indicates the page.
  1061. ;
  1062. ; Returns:
  1063. ;    DX    = Current cursor position.
  1064. ;    CX    = Current cursor scan lines.
  1065. ; Register(s) destroyed: AX,BX
  1066. ;-
  1067. get_curpos proc    near
  1068.     @GetCur    video_page
  1069.     ret
  1070. get_curpos    endp
  1071.  
  1072.  
  1073. ;+
  1074. ; FUNCTION : set_disp_marks
  1075. ;
  1076. ;    Sets the marks disp_begin and disp_end to indicate the start
  1077. ;    and end positions in the line that have been changed. The
  1078. ;    routine is passed two parameters which indicate
  1079. ;    the potentially new values for disp_begin and disp_end
  1080. ;    respectively. However the global disp_begin is changed only if
  1081. ;    the new value is less than the current value. Similarly
  1082. ;    disp_end is changed only if the new value is greater than the
  1083. ;    current value.
  1084. ;
  1085. ; Parameters:
  1086. ;    AX    = potential disp_end
  1087. ;    DX    = potential disp_begin
  1088. ;
  1089. ; Returns:
  1090. ;    Nothing.
  1091. ;    May set globals disp_begin and disp_end.
  1092. ;
  1093. ; Register(s) destroyed: None.
  1094. ;-
  1095. set_disp_marks    proc near
  1096.     cmp    ax,disp_end        ;New value greater ?
  1097.     jb    @set_disp_marks_10    ;No
  1098.     mov    disp_end,ax        ;New disp_end
  1099. @set_disp_marks_10:
  1100.     cmp    dx,disp_begin        ;New value smaller
  1101.     jnb    @set_disp_marks_20    ;No
  1102.     mov    disp_begin,dx        ;New disp_begin
  1103. @set_disp_marks_20:
  1104.     ret
  1105. set_disp_marks    endp
  1106.  
  1107.  
  1108. ;+
  1109. ; FUNCTION : disp_line
  1110. ;
  1111. ;    Displays the current contents of the line buffer. Since the
  1112. ;    entire line is not redisplayed everytime, all procedures that
  1113. ;    change the contents of the line buffer have to follow certain
  1114. ;    rules in order to make sure the display correctly shows the
  1115. ;    line. The variable disp_begin must be set to the earliest
  1116. ;    position in the line that has been changed and disp_end to beyond
  1117. ;    last position in the line that has been changed.;
  1118. ; Parameters:
  1119. ;    None.
  1120. ;
  1121. ; Returns:
  1122. ;    Nothing
  1123. ; Register(s) destroyed:
  1124. ;-
  1125. disp_line proc near
  1126.     @save    si,di
  1127.     mov    ax,disp_begin        ;Lower limit of changed chars
  1128.     mov    si,ax
  1129.     mov    cx,disp_end        ;CX->byte after last char that
  1130. ;                     has changed
  1131.     sub    cx,si            ;CX<-num chars to be output
  1132.     jcxz    @disp_line_90        ;Nothing to be updated
  1133.     push    cx            ;Save CX across calls
  1134.     call    near ptr line_to_scr    ;Move cursor to corresponding
  1135. ;                     position on the screen.
  1136. ;    OK, now we are ready to begin updating the screen.
  1137.     call    near ptr get_curpos    ;DX<-current cursor position
  1138.     pop    cx            ;Restore CX
  1139.     mov    di,lastchar        ;DI->beyond last char
  1140.     cmp    si,di            ;Beyond last char?
  1141.     je    @disp_line_25        ;Go display blanks
  1142. @disp_line_10:                ;Loop to output chars
  1143.     lodsb                ;AL<-next char
  1144.     @DispCh    al            ;Display it
  1145.     push    cx            ;Save CX
  1146.     push    dx            ;Save old cursor position
  1147.     call    near ptr get_curpos    ;DX<-new cursor position
  1148.                     ; BX destroyed
  1149.     pop    bx            ;BX<-old cursor position
  1150.     pop    cx            ;Restore CX
  1151.     or    dl,dl            ;Column 0 ?
  1152.     jne    @disp_line_20        ;Nope
  1153.                     ;Col 0
  1154.     cmp    bh,dh            ;Is the row the same
  1155.     jne    @disp_line_20
  1156.                     ;yes, screen scrolled
  1157. ;    dec    initial_curpos+1    ;changed to next line by wd
  1158.     dec    initial_currow        ;Decrement the row for initial
  1159. ;                     cursor position
  1160. @disp_line_20:
  1161.     mov    bx,dx            ;New cursor position
  1162.     cmp    si,di            ;Beyond last char?
  1163.     loopne    @disp_line_10        ;Keep looping until count exhausted or 
  1164. ;                     beyond last char
  1165. @disp_line_25:
  1166. ;    Now all changed positions have been displayed. If CX is not 0, 
  1167. ;    then the remaining char positions have to be 
  1168. ;    replaced with blanks. Note that since we are now overwriting  
  1169. ;    previously displayed positions, no need to check for line 
  1170. ;    wraparound or scroll. 
  1171.  
  1172.     jcxz    @disp_line_90        ;No more chars
  1173.  
  1174.     mov    al,' '            ;Overwrite with blanks
  1175. @disp_line_30:
  1176.     @DispCh    al
  1177.     loop    @disp_line_30
  1178. @disp_line_90:
  1179.     mov    ax,dot
  1180.     mov    disp_begin,ax        ;Initialize for next call
  1181.     mov    disp_end,ax
  1182.     call    near ptr line_to_scr    ;Set cursor at dot
  1183.  
  1184.     @restore
  1185.     ret
  1186. disp_line endp
  1187.  
  1188.  
  1189.  
  1190.  
  1191.  
  1192. ;+
  1193. ; FUNCTION : line_to_scr
  1194. ;
  1195. ;    Places the cursor at the screen position corresponding to a
  1196. ;    specific position in the line buffer. The entire line buffer
  1197. ;    upto that position must have been displayed before.
  1198. ;
  1199. ; Parameters:
  1200. ;    AX    = Pointer into the line buffer
  1201. ;
  1202. ; Returns:
  1203. ;    Nothing.
  1204. ; Register(s) destroyed: AX, BX, DX
  1205. ;-
  1206. line_to_scr proc near
  1207.     sub    ax,offset dgroup:linebuf ;ax<-num chars
  1208.     mov    dx,initial_curpos    ;Initial cursor position
  1209. ;                     dh<-row, dl<-column
  1210.     xor    bh,bh
  1211.     mov    bl,dl            ;BX<-original column
  1212.     add    ax,bx            ;Compensate for initial position.
  1213. ;                     AX is now the 'virtual column'
  1214.     mov    bl,screen_width        ;BX<-width of screen
  1215. @line_to_scr_10:            ;Loop to skip over chars that
  1216. ;                     do not need to be updated
  1217.     cmp    ax,bx            ;Num of chars fit on a line?
  1218.     jb    @line_to_scr_20        ;Yes, exit loop
  1219.     sub    ax,bx            ;Go to next line
  1220.     inc    dh            ;Increment the row
  1221.     jmp    short @line_to_scr_10
  1222. @line_to_scr_20:
  1223. ; al now contains the column and dh the row where the cursor should
  1224. ; be placed 
  1225.     mov    dl,al            ;dx<-screen position
  1226.     @SetCurPos ,,video_page        ;Set the cursor position
  1227.     ret
  1228. line_to_scr endp
  1229.  
  1230.  
  1231.  
  1232.  
  1233. ;+
  1234. ; FUNCTION : insert_chars
  1235. ;
  1236. ;    Inserts a string of chars at the specified position in the
  1237. ;    linebuffer. If the length would exceed the size of the line buffer,
  1238. ;    chars are only store until the buffer is full and the carry flag is
  1239. ;    set. Dot is updated appropriately.
  1240. ;
  1241. ; Parameters :
  1242. ;
  1243. ;    SI    - ptr to source string
  1244. ;    DI    - ptr to insert position. This must lie in the line buffer.
  1245. ;    AX    - length of source string
  1246. ;
  1247. ; Returns:
  1248. ;    CF    = 1 if could not be fitted into linebuf
  1249. ;          0 otherwise
  1250. ;
  1251. ; Registers destroyed:
  1252. ;    AX,CX,DX
  1253. insert_chars proc near
  1254.     @save    si,di
  1255.     mov    dx,di            ;Save insert position in DX
  1256.     mov    di,lastchar        ;First empty position
  1257.     mov    cx,offset DGROUP:linebuf_suffix
  1258.     sub    cx,di            ;Subtract current last position
  1259. ;                     CX<-max chars that will fit
  1260.     cmp    cx,ax            ;Will all chars fit ?
  1261.     jb    @insert_chars_5    ;Not all chars will fit
  1262.     xchg    ax,cx            ;All chars will fit
  1263. @insert_chars_5:
  1264. ;    CX is number of chars to insert
  1265.     pushf                ;Remember CF
  1266. ;    Make place for the characters to be inserted by moving current
  1267. ;    characters up by CX.
  1268.     mov    ax,di
  1269.     sub    ax,dx            ;AX<-num chars to move
  1270.     push    si            ;Remember source address
  1271.     mov    si,di            ;SI->first char to be moved
  1272.     add    di,cx            ;DI -> new value of lastchar
  1273.     mov    lastchar,di        ;Store it
  1274.     xchg    ax,cx            ;AX<-num chars to insert
  1275. ;                     CX<-num chars to move
  1276.     std                ;Direction is downward
  1277.     cmpsb                ;Decrement SI,DI
  1278.     rep    movsb            ;Make place
  1279.     cld
  1280.     pop    si            ;Restore string source
  1281. ; Before inserting the chars, update the dot if it is affected.
  1282.     cmp    dx,dot            ;Is the dot at or after the insert
  1283. ;                     position ?
  1284.     jb    @insert_chars_50    ;No, jump
  1285.     add    dot,ax            ;Else update the dot
  1286. @insert_chars_50:
  1287.     mov    di,dx            ;DI->insert position
  1288.     xchg    cx,ax            ;CX<-num chars to insert
  1289.     rep    movsb            ;Copy string into linebuffer
  1290.     mov    ax,lastchar
  1291.     call    near ptr set_disp_marks    ;AX,DX are parameters
  1292.     popf                ;Restore CF
  1293.  
  1294.     @restore
  1295.     ret
  1296. insert_chars endp
  1297.  
  1298.  
  1299. ;+
  1300. ; FUNCTION : insert_at_dot
  1301. ;
  1302. ;    Inserts a string of characters into the line buffer in the
  1303. ;    position pointed to by dot. If the length specified in global
  1304. ;    caller_buflen will be exceeded,chars are only stored until the
  1305. ;    buffer is full and CF is set.
  1306. ;
  1307. ; Parameters:
  1308. ;    SI    = ptr to source string
  1309. ;    AL    = length of string
  1310. ;
  1311. ; Returns:
  1312. ;    CF    = 1 if could not be fitted into linebuf
  1313. ;          0 otherwise
  1314. ; Register(s) destroyed:
  1315. ;    <TBA>
  1316. ;-
  1317. insert_at_dot proc near
  1318.     @save    si,di,dx
  1319.     xor    ah,ah            ;AX<-length of source string
  1320.     mov    di,dot            ;DI-> insert position
  1321.     call    near ptr insert_chars    ;Params SI,DI,AX, returns status in CF
  1322.     @restore
  1323.     ret
  1324. insert_at_dot endp
  1325.  
  1326.  
  1327.  
  1328.  
  1329. ;+
  1330. ; FUNCTION : remove_chars
  1331. ;
  1332. ;    Removes a string of chars at the specified position in the
  1333. ;    linebuffer. The display markers and the lastchar global are updated
  1334. ;    accordingly. 
  1335. ;
  1336. ; Parameters :
  1337. ;
  1338. ;    SI    - ptr to position in linebuf from which to delete
  1339. ;    AX    - number of chars to delete.
  1340. ;
  1341. ; Returns:
  1342. ;    Nothing.
  1343. ;
  1344. ; Registers destroyed:
  1345. ;    AX,CX,DX
  1346. remove_chars proc near
  1347.     @save    si,di
  1348.     mov    di,ax            ;Save delete count
  1349.  
  1350. ; First update the display markers
  1351.     mov    ax,lastchar
  1352.     mov    dx,si
  1353.     call    near ptr set_disp_marks    ;AX,DX params
  1354.     mov    ax,lastchar
  1355.     sub    ax,si            ;Num chars after delete position
  1356.     cmp    ax,di            ;More than the specified number ?
  1357.     jb    @remove_chars_10    ;No, so just delete that many bytes
  1358.     mov    ax,di
  1359. @remove_chars_10:
  1360. ; AX is number of bytes to delete. See if the dot needs to be updated.
  1361.     mov    di,si            ;DI->delete position
  1362.     add    si,ax            ;SI->first char after delete string
  1363.     cmp    di,dot
  1364.     jnb    @remove_chars_40    ;dot before delete pos, so
  1365. ;                     unaffected
  1366.     cmp    si,dot            ;Is dot beyond it delete range
  1367.     jb    @remove_chars_30    ;Yes
  1368. ; dot is in delete region. Update it to point to first delete position
  1369.     mov    dot,di
  1370.     jmp    short @remove_chars_40
  1371. @remove_chars_30:
  1372. ; dot is beyond delete position. So subtract delete bytes from it.
  1373.     sub    dot,ax
  1374.  
  1375. @remove_chars_40:
  1376. ; Now that the screen markers and dot have been updated, get down to the
  1377. ; real business at hand. SI points to first char after delete string, DI is
  1378. ; the delete position. AX is number of bytes to be deleted.
  1379.     mov    cx,lastchar
  1380.     sub    lastchar,ax        ;Update lastchar
  1381.     sub    cx,si            ;CX<-num bytes to move
  1382.     rep    movsb            ;Move 'em
  1383. ; All done
  1384.  
  1385.     @restore
  1386.     ret
  1387. remove_chars endp
  1388.  
  1389.  
  1390. ;+
  1391. ; FUNCTION : erase_to_dot
  1392. ;
  1393. ;    Deletes all characters from the line buffer between the
  1394. ;    positions AX and dot. (Either AX or dot may be specify the
  1395. ;    beginning of range to be deleted). The markers disp_begin and
  1396. ;    disp_end are set to reflect the changed positions in the line.
  1397. ;    Global lastchar is also updated.
  1398. ; Parameters:
  1399. ;    AX    = One endpoint of the range to be deleted.
  1400. ;    Global    dot is the other.
  1401. ; Returns:
  1402. ;    Nothing.
  1403. ; Register(s) destroyed:
  1404. ;-
  1405. erase_to_dot proc near
  1406.     @save    si
  1407.     mov    si,dot
  1408.     cmp    ax,si            ;Make sure AX is after dot
  1409.     jnb    @erase_to_dot_10    ;Yes it is
  1410.     xchg    si,ax            ;Else exchange
  1411. @erase_to_dot_10:            ;AX is low end, SI high end
  1412.     sub    ax,si            ;AX is num bytes to delete
  1413.     call    near ptr remove_chars    ;Delete AX chars starting at [SI]
  1414.     @restore
  1415.     ret
  1416. erase_to_dot endp
  1417.  
  1418.  
  1419. ;+
  1420. ; FUNCTION : cmdedit_cmd
  1421. ;
  1422. ;    Checks if the line buffer contains a CMDEDIT command and if so
  1423. ;    executes it.
  1424. ;
  1425. ; Parameters:
  1426. ;    None.
  1427. ;
  1428. ; Returns:
  1429. ;    CF    = 0 if the line was a command
  1430. ;          1 otherwise.
  1431. ; Register(s) destroyed:
  1432. ;    AX,BX,CX,DX
  1433. ;-
  1434. cmdedit_cmd proc near
  1435.     @save    si,di
  1436.     mov    si,offset DGROUP:linebuf    ;SI->linebuf
  1437.     mov    di,lastchar            ;DI->end of line in linebuf
  1438. ; Skip leading whitespace
  1439.     mov    cx,di
  1440.     sub    cx,si                ;CX<-num chars in linebuf
  1441.     call    near ptr skip_whitespace    ;SI->first non-whitespace char
  1442. ;                         CX<-num remaining chars
  1443.     jcxz    @cmdedit_cmd_99            ;No command on line
  1444.     mov    di,si                ;DI->first char of word
  1445. ; Skip first word (name of this command)
  1446.     call    near ptr skip_nonwhite        ;SI->first whitespace after
  1447. ;                             command name
  1448. ;                         CX<-num remaining chars
  1449.     mov    ax,si
  1450.     sub    ax,di                ;AX<-num chars in word
  1451.     cmp    ax,MAX_CMD_LEN            ;Word too long to be command?
  1452.     ja    @cmdedit_cmd_98            ;Yes, exit
  1453. ; Now search thru the command table to see if the first word in the line is a
  1454. ; CMDEDIT command. Currently, DI->start of word, AX = num chars in word
  1455.     xor    dx,dx                ;DX<-Command number
  1456.     mov    si,offset dgroup:cmd_table    ;SI->Start of commands
  1457.  
  1458. @cmdedit_cmd_10:
  1459.     xor    ch,ch                ;Clear high bits
  1460.     mov    cl,[si]                ;CX<-Length of command
  1461.     jcxz    @cmdedit_cmd_98            ;End of table, exit
  1462.     inc    si                ;SI->command
  1463.     cmp    cx,ax                ;Lengths match
  1464.     jne    @cmdedit_cmd_30            ;No, go try next command
  1465.     xchg    bx,ax                ;BX<-num chars in word
  1466.     call    near ptr stre_cmp        ;Compare strings
  1467.     xchg    ax,bx                ;AX<-num chars in word
  1468.     je    @cmdedit_cmd_50            ;Command matched
  1469.  
  1470. @cmdedit_cmd_30:
  1471.     xor    ch,ch
  1472.     mov    cl,-1[si]            ;AX<-length of command
  1473.     add    si,cx                ;SI->length of next command
  1474.     inc    dx                ;Increment the command number
  1475.     jmp    short @cmdedit_cmd_10        ;Try next command
  1476.  
  1477. @cmdedit_cmd_50:                ;Found command
  1478.     mov    si,di                ;SI->first char of command
  1479.     add    si,ax                ;SI->first char after command
  1480.     mov    cx,lastchar
  1481.     sub    cx,si                ;CX<-num chars after command
  1482.     mov    di,dx                ;BX<-command number
  1483.     shl    di,1                ;BX<-offset into table
  1484.     call    cmd_func_table[di]        ;Execute it
  1485. ;                         Params:
  1486. ;                         SI->first char after command
  1487. ;                         CX = remaining length of line
  1488. ;                         (after command)
  1489.     IF  EXTRA_HANDLER   ;added by wd
  1490.     cmp    source,offset DGROUP:get_int21_line
  1491.     jne    @cmdedit_cmd_55
  1492.     mov    source,offset DGROUP:get_kbd_line
  1493.     mov    lastchar,offset DGROUP:linebuf
  1494.     mov    user_command,1
  1495. @cmdedit_cmd_55:
  1496.     ENDIF
  1497.     cmp    source,offset DGROUP:get_kbd_line
  1498.     jne    @cmdedit_cmd_60
  1499.     call    near ptr output_newline ;this and next 2 lined added by wd
  1500.     cmp    user_command,1          ;If line's being returned to dos
  1501.     je    @cmdedit_cmd_60         ;skip the prompt
  1502.     call    near ptr disp_prompt        ;Display user prompt
  1503. @cmdedit_cmd_60:
  1504.     clc                    ;CF = 0
  1505.     jmp    short @cmdedit_cmd_99
  1506. @cmdedit_cmd_98:                ;No command found
  1507.     stc                    ;CF = 1
  1508. @cmdedit_cmd_99:
  1509.     @restore
  1510.     ret
  1511. cmdedit_cmd endp
  1512.  
  1513.  
  1514.  
  1515.  
  1516. ;+
  1517. ; FUNCTION : abort_processing
  1518. ;
  1519. ;    Called by various routines in case of any errors that require
  1520. ;    aborting of any ongoing processing. An error message is
  1521. ;    displayed and CMDEDIT state is reset to accept input from the
  1522. ;    keyboard. The routine adjusts the stack pointer to a previously
  1523. ;    stored state. Execution then continues at a `abort entry'
  1524. ;    point. The routine does NOT return to the caller.
  1525. ;
  1526. ; Parameters:
  1527. ;    AX    = Error message number.
  1528. ;
  1529. ; Returns:
  1530. ;    Does NOT return to caller.
  1531. ;
  1532. ; Register(s) destroyed:
  1533. ;    Potentially all but irrelevant since routine does not return to
  1534. ;    caller.
  1535. ;-
  1536. abort_processing proc near
  1537.     mov    macro_level,0            ;Reset macro level
  1538.     mov    source,offset DGROUP:get_kbd_line ;Set input to keyboard
  1539.  
  1540. ; Display a message
  1541.     mov    di,offset DGROUP:linebuf
  1542.     mov    dot,di                ;dot MUST be at
  1543. ;                         beginning of line
  1544. ;                         since this position is
  1545. ;                         stored in the main routine
  1546.  
  1547.     cmp msg_flag,0                ;following added/changed
  1548.     jne @dfa1                ;by dfa
  1549.     mov si,offset DGROUP:abort_msg_hd    ;
  1550.     mov cx,ABORT_HDR_LEN            ;
  1551.     jmp short @dfa2             ;
  1552. @dfa1:                        ;
  1553.     mov si,offset DGROUP:abort_msg_hd2    ;
  1554.     mov cx,ABORT_HDR2_LEN            ;
  1555. @dfa2:                        ;now back to original...
  1556.  
  1557.     rep    movsb                ;Copy message header
  1558.     sal    ax,1
  1559.     sal    ax,1                ;AX is now index into msg table
  1560.     xchg    ax,bx
  1561.     mov    si,abort_msg_ptrs[bx]        ;SI->message
  1562.     mov    cx,abort_msg_ptrs[bx+2]        ;CX<-length of message
  1563.     rep    movsb                ;Copy msg into linebuf
  1564.  
  1565.     cmp msg_flag,0                ;following added/changed
  1566.     jne @dfa3                ;by dfa
  1567.     mov si,offset DGROUP:abort_msg_tl    ;
  1568.     mov cx,ABORT_TAIL_LEN            ;
  1569.     jmp short @dfa4             ;
  1570. @dfa3:                        ;
  1571.     mov si,offset DGROUP:abort_msg_tl2    ;
  1572.     mov cx,ABORT_TAIL2_LEN            ;
  1573. @dfa4:                        ;now back to original...
  1574.  
  1575.     rep    movsb                ;Copy tail of message
  1576.     mov    lastchar,di
  1577.     mov    ax,di                ;Set display marks
  1578.     mov    dx,offset DGROUP:linebuf
  1579.     call    near ptr set_disp_marks
  1580.     call    disp_line            ;Display message
  1581.     call    near ptr restore_cursor        ;Restore cursor to user shape
  1582.     call    near ptr output_newline
  1583.     call    near ptr disp_prompt
  1584.     mov    sp,abort_entry_stack
  1585.     jmp    near ptr cmdedit_abort_entry
  1586.  
  1587. abort_processing endp
  1588.  
  1589.  
  1590.  
  1591. ;+
  1592. ; FUNCTION : restore_cursor
  1593. ;
  1594. ;    Restores the cursor to the user's shape.
  1595. ;
  1596. ; Parameters:
  1597. ;    Global caller_cursor contains original shape
  1598. ;
  1599. ; Returns:
  1600. ;    
  1601. ; Register(s) destroyed:
  1602. ;    None.
  1603. ;-
  1604. restore_cursor    proc near
  1605.     @save    ax,cx
  1606.     mov    cx,caller_cursor
  1607.     IF    TOGGLE_CURSOR
  1608.     @SetCurSz ch,cl
  1609.     ENDIF
  1610.     @restore
  1611.     ret
  1612. restore_cursor    endp
  1613.  
  1614.  
  1615. ;+
  1616. ; FUNCTION : reset_line
  1617. ;
  1618. ;    Called to init various things like cursor shape, history buffer
  1619. ;    character positions etc.
  1620. ;
  1621. ; Parameters:
  1622. ;    None.
  1623. ;
  1624. ; Returns:
  1625. ;    Nothing.
  1626. ;
  1627. ; Register(s) destroyed:
  1628. ;    AX,BX,CX,DX
  1629. ;-
  1630. reset_line proc near
  1631.     call    near ptr hist_top    ;Reset history stack ptr to top
  1632.     call    near ptr restore_cursor    ;Reset cursor shape
  1633.     mov    ax,offset dgroup:linebuf
  1634.     mov    lastchar,ax        ;End of line
  1635.     mov    dot,ax            ;current pos in line
  1636.     mov    disp_begin,ax        ;first pos that changed
  1637.     mov    disp_end,ax        ;last pos that changed
  1638.  
  1639. ; Init overstrike/insert mode
  1640.     mov    bl,default_imode    ;Default edit mode
  1641. ;                     (insert/overstrike) 
  1642.     mov    edit_mode,bl        ;Init insert/overtype mode
  1643.  
  1644. ; Initialize the cursor shapes for insert and overstrike mode
  1645. ; dfa added cursor_type toggle for swapping insert/overtype shapes.
  1646.     mov    ax,caller_cursor    ;Caller's cursor shape
  1647.     IF    TOGGLE_CURSOR
  1648.     mov    ah,al
  1649.     sub    ah,3
  1650.     mov    imode_cursor,ax     ;Insert mode cursor
  1651.     mov    omode_cursor,ax     ;Overtype mode cursor
  1652.     mov    ah,al
  1653.     sub    ah,1
  1654.     cmp    cursor_type,0
  1655.     jnz    short dfa1
  1656.     mov    omode_cursor,ax     ;Overtype mode cursor
  1657.     jmp    short dfa2
  1658. dfa1:
  1659.     mov    imode_cursor,ax     ;Insert mode cursor
  1660. dfa2:
  1661. ; Init cursor shape
  1662.     xor    bh,bh
  1663.     add    bx,bx
  1664.     mov    cx,omode_cursor[bx]
  1665.     mov    ah,01h
  1666.     int    10h
  1667.  
  1668.     ELSE
  1669.  
  1670.     mov    omode_cursor,ax
  1671.     mov    imode_cursor,ax
  1672.  
  1673.     ENDIF
  1674.  
  1675.     mov    bh,video_page
  1676.     @GetCur bh
  1677.     mov    initial_curpos,dx    ;Initial cursor position
  1678.  
  1679.     ret
  1680. reset_line endp
  1681.  
  1682.  
  1683. ;+
  1684. ; FUNCTION : init_screen
  1685. ;
  1686. ;    Inits various screen parameters. Reads the current prompt from
  1687. ;    the screen and store in the prompt buffer. prompt buffer is
  1688. ;    assumed to be at most the width of the screen.
  1689. ;
  1690. ; Parameters:
  1691. ;    None.
  1692. ;
  1693. ; Returns:
  1694. ;    Nothing.
  1695. ; Register(s) destroyed:
  1696. ;    AX,BX,CX,DX
  1697. ;-
  1698. init_screen proc near
  1699.     @save    si,di
  1700.     @GetMode            ;Get the video mode
  1701.     mov    video_page,bh        ;Store page
  1702.     mov    screen_width,ah        ; and width of display
  1703.  
  1704.     @GetCur    bh            ;Get the cursor shape and position
  1705.     mov    initial_curpos,dx    ;Initial cursor position
  1706.     mov    caller_cursor,cx    ;Caller's cursor shape
  1707.  
  1708.     mov    di,offset DGROUP:prompt
  1709.     mov    cx,PROMPT_BUF_SIZE    ;CX<-size of prompt buffer
  1710. ;                     (assumed not 0)
  1711.     mov    si,dx            ;DX<-cursor pos
  1712.     xor    dl,dl            ;DX<-position at start of row
  1713.  
  1714. @init_screen_5:
  1715. ; BH holds video page, DX is cursor position, SI is ending cursor
  1716. ; position, CX is remaining space in prompt buffer
  1717.     @SetCurPos    ,,bh        ;Set cursor position
  1718.     cmp    dx,si            ;Reached original position ?
  1719.     je    @init_screen_10        ;Yes, all done
  1720.     @GetChAtr    bh        ;Get char at cursor
  1721.     stosb                ;Store in prompt buffer
  1722.     inc    dl            ;Increment cursor position
  1723.     loop    @init_screen_5        ;loop unless prompt buffer full
  1724. @init_screen_10:
  1725.     sub    di,offset DGROUP:prompt
  1726.     mov    prompt_length,di    ;Store length of prompt
  1727.  
  1728.     @restore
  1729.     ret
  1730. init_screen endp
  1731.  
  1732.  
  1733.  
  1734. ;+
  1735. ; FUNCTION : disp_prompt
  1736. ;
  1737. ;    Called to display the user's prompt. The prompt is taken from
  1738. ;    the buffer 'prompt'.
  1739. ;
  1740. ; Parameters:
  1741. ;    None.
  1742. ;
  1743. ; Returns:
  1744. ;    Nothing.
  1745. ; Register(s) destroyed:
  1746. ;    <TBA>
  1747. ;-
  1748. disp_prompt    proc near
  1749.     @save    si
  1750.     call    near ptr output_newline
  1751.     mov    cx,prompt_length
  1752.     jcxz    @disp_prompt_99
  1753.     mov    si,offset DGROUP:prompt
  1754. @disp_prompt_10:
  1755.     lodsb
  1756.     @DispCh    al
  1757.     loop    @disp_prompt_10
  1758. @disp_prompt_99:
  1759.     @restore
  1760.     ret
  1761. disp_prompt    endp
  1762.  
  1763.  
  1764.  
  1765.  
  1766. ;+
  1767. ; FUNCTION : makeroom
  1768. ;
  1769. ;    Called to push a specified number of characters from the end of a
  1770. ;    line to the back of the line buffer.
  1771. ;
  1772. ; Parameters:
  1773. ;    CX    - number of chars to push back
  1774. ;
  1775. ; Returns:
  1776. ;    DI    - points to the first char of the string pushed back.
  1777. ; Register(s) destroyed:
  1778. ;    CX
  1779. ;-
  1780. makeroom proc near
  1781.     @save    si
  1782.     mov    si,lastchar        ;end of line
  1783.     dec    si
  1784.     mov    di,offset DGROUP:linebuf_suffix ;Di->end of linebuf (we
  1785. ;                         want to move chars in
  1786. ;                         reverse order) 
  1787.     std
  1788.     rep    movsb            ;Move up characters
  1789.     cld
  1790.     inc    di            ;DI->start of string
  1791.     @restore
  1792.     ret
  1793. makeroom endp
  1794.  
  1795.  
  1796. ;+
  1797. ; FUNCTION : getpsp
  1798. ;
  1799. ;    Returns the PSP of the current process
  1800. ;
  1801. ; Returns:
  1802. ;    BX - segment of current PSP
  1803. ;
  1804. ; Registers destroyed :
  1805. ;    AX,BX
  1806. ;-
  1807. getpsp proc near
  1808. ; Get the PSP of the current process
  1809.     cmp    dos_version_major,2
  1810.     jbe    @getpsp_10
  1811. ;    DOS 3.x or above - use documented call
  1812.     mov    ah,62h
  1813.     jmp    short @getpsp_90
  1814. @getpsp_10:        
  1815. ; DOS version 2.x - use undocumented call
  1816.     mov    ah,51h
  1817. @getpsp_90:
  1818.     int    21h                ;BX->PSP segment
  1819.     ret
  1820. getpsp endp
  1821.     
  1822.  
  1823.  
  1824. ;+
  1825. ; Function : locate_dosenv
  1826. ;
  1827. ;    Locates the segment in which the current environment is located.
  1828. ;    This environment is the 'current' environment which may not
  1829. ;    necessarily be the root environment.
  1830. ;
  1831. ; Parameters:
  1832. ;    None.
  1833. ;
  1834. ; Returns:
  1835. ;    AX    - segment of environment
  1836. ;
  1837. ; Register(s) destroyed:
  1838. ;    AX
  1839. ;-
  1840. locate_dosenv proc near
  1841.     @save    bx,si,es
  1842.  
  1843.     call    near ptr getpsp            ;BX->segment of psp
  1844.     mov    es,bx                ;ES->segment of psp
  1845.  
  1846. ;    Loop to find the current command.com psp
  1847.     mov    si,16h                ;ES:SI->parent psp
  1848.     xor    ax,ax                ;Init for loop
  1849.     jmp    short @locate_dosenv_20        ;'while' loop
  1850.     
  1851. @locate_dosenv_10:
  1852.     mov    ax,es:[si]            ;AX<-psp seg
  1853.     mov    es,ax                ;ES->psp of parent
  1854. @locate_dosenv_20:
  1855.     cmp    ax,es:[si]            ;Is psp == parent psp ?
  1856.     jne    @locate_dosenv_10
  1857.  
  1858. ; ES contains DOS PSP.
  1859.     mov    ax,es:[2ch]            ;Offset 2c is env address
  1860.  
  1861. ; AX->DOS environment
  1862. ;    mov    dos_envseg,ax
  1863.     cmp    dos_version_major,2        ;DOS 2.x ?
  1864.     je    @locate_dosenv_50
  1865. ; Versions 3.x or higher
  1866.     cmp    dos_version_minor,10        ;3.1 or below ?
  1867.     jle    @locate_dosenv_50        ;If so handle like 2.x
  1868.     cmp    dos_version_minor,30        ;3,3 or above ?
  1869.     jge    @locate_dosenv_99        ;Then all done
  1870. ; DOS version higher than 3.1 but below 3.3.
  1871.     jmp    short @locate_dosenv_60
  1872.  
  1873.  
  1874. @locate_dosenv_50:
  1875. ; DOS version 2.x-3.1. If the environement is non-0, all done. Else the
  1876. ; environment is the memory block below the command.com.
  1877.     or    ax,ax                ;0 ?
  1878.     jne    @locate_dosenv_99        ;No, all done
  1879. @locate_dosenv_60:
  1880.     mov    si,es
  1881.     dec    si                ;SI is segment of memory
  1882. ;                         control block of command.com
  1883.     mov    es,si
  1884.     mov    ax,es:[3]            ;AX->size of command.com in
  1885. ;                         paragraphs 
  1886.     inc    ax                ;Add size of MCB to AX (in
  1887. ;                         paras) 
  1888.     add    ax,si                ;AX->MCB of environment
  1889.     inc    ax                ;AX->environment
  1890. ;    mov    dos_envseg,ax            ;Store it.
  1891.  
  1892. @locate_dosenv_99:
  1893. ; OK, now dos_envseg supposedly contains the environment segment. DO some
  1894. ; heuristics to make sure it is really what we think it is.
  1895.     
  1896.  
  1897.     @restore
  1898.     ret
  1899. locate_dosenv endp
  1900.  
  1901.  
  1902.  
  1903. ;+
  1904. ; FUNCTION : our_break_handler
  1905. ;
  1906. ;    This takes over the Ctrl-Break interrupt and sets a flag when
  1907. ;    Ctrl-Break is hit. It then jumps to the original Ctrl-Break handler.
  1908. ;
  1909. ; Parameters:
  1910. ;    
  1911. ;
  1912. ; Returns:
  1913. ;    
  1914. ; Register(s) destroyed:
  1915. ;-
  1916. our_break_handler proc near
  1917.     inc    CS:check_break
  1918.     cmp    CS:trap_break,1
  1919.     jne    @our_break_handler_10
  1920.     iret
  1921. @our_break_handler_10:
  1922.     jmp    CS:prev_isr1b
  1923. our_break_handler endp
  1924.  
  1925. CSEG    ENDS
  1926.  
  1927.     END    entry
  1928.